package rodrigosetti.colorstrike.fase;

import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.Sprite;

import rodrigosetti.colorstrike.core.Vetor2D;
import rodrigosetti.midpgame.Estado;
import rodrigosetti.midpgame.GameCore;

public abstract class Fase implements Estado {
    
    private Vector primeiroPlano, segundoPlano;
    
    protected int limiteQueda;
    protected float atrito, atritoAr;
    protected float gravidade;
    protected String nome;
    protected Elemento elementos[];
    protected int posInicialX, posInicialY;
    
    public Vetor2D foco;
    public Informacao informacaoAtiva;
    public Heroi heroi;
    
    public Fase() {
        segundoPlano = new Vector();
        primeiroPlano = new Vector();
        informacaoAtiva = null;
    }
    
    /**
     * Seta heroi e foco
     *
     * @param heroi
     */
    protected void setHeroi(Heroi heroi, int posicao) {
        this.heroi = heroi;
        heroi.posicaoVetor = posicao;
        
        posInicialX = (int)heroi.getX();
        posInicialY = (int)heroi.getY();
        
        this.reiniciar();
    }
    
    /**
     * Reinicia fase
     */
    public void reiniciar() {
        if (!primeiroPlano.contains(heroi))
            primeiroPlano.addElement(heroi);
        
        heroi.posicao.x = posInicialX;
        heroi.posicao.y = posInicialY;
        foco = heroi.posicao;
        heroi.vida = true;
        heroi.morrendo = false;
        heroi.sprite.setTransform(Sprite.TRANS_NONE);
    }
    
    /* Verifica se elemento eh visivel */
    public boolean visivel(Elemento e) {
        return (((e.getX()+ e.getWidth() >= foco.x - GameCore.widthScreen) &&
                (e.getX() <= foco.x + GameCore.centerX)) &&
                ((e.getY()+ e.getHeight() >= foco.y - GameCore.heightScreen) &&
                (e.getY() <= foco.y + GameCore.centerY)));
    }
    
    
    /**
     * Determina limites, atualiza e interage elementos
     */
    public int atualizar() {
        /**
         * Se tem uma informacao ativa na tela
         */
        if (informacaoAtiva != null) {
            /**
             * Verifica se usuario pressionou FIRE
             */
            if ((GameCore.teclas & GameCore.KEY_FIRE) > 0) {
                informacaoAtiva.ativo = false;
                informacaoAtiva = null;
                GameCore.limparTecla();
            }
            return heroi.getEstado();
        }
        
        /* Percorre lista de elementos visiveis, para retirar os nao visiveis */
        for (Enumeration en = segundoPlano.elements();en.hasMoreElements();) {
            Elemento e  = (Elemento)en.nextElement();
            if (!this.visivel(e)) {
                segundoPlano.removeElement(e);
            }
        }
        
        /* Percorre lista de elementos visiveis, para retirar os nao visiveis */
        for (Enumeration en = primeiroPlano.elements();en.hasMoreElements();) {
            Elemento e  = (Elemento)en.nextElement();
            if (!this.visivel(e)) {
                primeiroPlano.removeElement(e);
                ((Interagivel)e).onHide();
            }
        }
        
        
        /* Percorre lista de elementos para ver o que eh visivel */
        for (int i = 0; i < elementos.length; i++) {
            /* Se eh visivel */
            if (this.visivel(elementos[i]))
	    {
                
                /* se eh interagivel e nao contem */
                if (elementos[i] instanceof Interagivel)
		{
		    if (!primeiroPlano.contains(elementos[i]))
		    {
			primeiroPlano.addElement(elementos[i]);
			((Interagivel)elementos[i]).onShow();
		    }
                }
                /* Adiciona a lista visivel, se nao contem */
		else if (!segundoPlano.contains(elementos[i]))
		{
                    segundoPlano.addElement(elementos[i]);
                }
            }
        }
        
        /* Atualiza elementos visiveis */
        for (Enumeration en = primeiroPlano.elements();en.hasMoreElements();) {
            Elemento e  = (Elemento)en.nextElement();
            
            if (e instanceof Interagivel && e.ativo) {
                ((Interagivel)e).atualizar();
                
                
                /* Interage com outros elementos */
                for (Enumeration en2 = segundoPlano.elements();en2.hasMoreElements();) {
                    Elemento e2 = (Elemento)en2.nextElement();
                    
                    /* Se nao eh o mesmo e esta ativo*/
                    if (e != e2 && e2.ativo) {
                        ((Interagivel)e).interagir(e2);
                    }
                }
                for (Enumeration en2 = primeiroPlano.elements();en2.hasMoreElements();) {
                    Elemento e2 = (Elemento)en2.nextElement();
                    
                    /* Se nao eh o mesmo e esta ativo*/
                    if (e != e2 && e2.ativo) {
                        ((Interagivel)e).interagir(e2);
                    }
                }
            }
        }
        
        /* Se passou do limite de queda */
        if (heroi.posicao.y > limiteQueda) {
            reiniciar();
        }
        
        return heroi.getEstado();
    }
    
    /**
     * Desenha elementos que estao em foco
     *
     * @param g
     */
    public void desenhar(Graphics g) {
        
        /* Desenha elementos visivies */
        for (Enumeration en = segundoPlano.elements();en.hasMoreElements();) {
            Elemento e = (Elemento)en.nextElement();
            if (e.ativo)
                e.desenhar(g);
        }
        /* Desenha elementos visivies */
        for (Enumeration en = primeiroPlano.elements();en.hasMoreElements();) {
            Elemento e = (Elemento)en.nextElement();
            if (e.ativo)
                e.desenhar(g);
        }
    }
    
    public void finalizar() {
        for (int i = 0; i < elementos.length; i++)
            elementos[i] = null;
        
        elementos = null;
        segundoPlano.removeAllElements();
        segundoPlano = null;
        primeiroPlano.removeAllElements();
        primeiroPlano = null;
        System.gc();
    }
}
